﻿using MediatR;
using Medical.Api.Read.Application.Command.DepartmentManagement.Sign;
using Medical.Api.Read.Dto.DepartmentManagement.Sign;
using Medical.Domain.DepartmentInfo;
using Medical.Domain.Wms;
using Medical.Domain.Enum;
using Medical.ErrorCode;
using Medical.Interstructrue.Base;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Medical.Api.Read.Application.Handler.DepartmentManagement.Sign
{
    /// <summary>
    /// 签收表查询处理器
    /// </summary>
    public class GetSignCommandHandler : IRequestHandler<GetSignCommands, ApiResult<List<SignDto>>>
    {
        private readonly ILogger<GetSignCommandHandler> logger;
        private readonly IBaseRepository<WmsLssue> lssueRep;
        private readonly IBaseRepository<WmsLssueDetail> lssueDetailRep;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        /// <param name="lssueRep">发放表仓储接口</param>
        /// <param name="lssueDetailRep">发放明细表仓储接口</param>
        public GetSignCommandHandler(
            ILogger<GetSignCommandHandler> logger,
            IBaseRepository<WmsLssue> lssueRep,
            IBaseRepository<WmsLssueDetail> lssueDetailRep)
        {
            this.logger = logger;
            this.lssueRep = lssueRep;
            this.lssueDetailRep = lssueDetailRep;
        }
        
        /// <summary>
        /// 处理签收表查询请求
        /// </summary>
        /// <param name="request">查询请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>签收表数据列表</returns>
        public async Task<ApiResult<List<SignDto>>> Handle(GetSignCommands request, CancellationToken cancellationToken)
        {
            try
            {
                logger.LogInformation($"开始查询签收表列表，发放时间：{request.LssueDate}");
                
                // 获取未删除的所有发放记录
                var query = lssueRep.GetAll().Where(x => !x.IsDeleted);
                
                // 只显示已发放的数据
                query = query.Where(x => x.LssueState == LssueTypeEnunm.已发放);
                
                // 如果提供了发放时间，则按发放时间筛选
                // 查询当天的记录（从当天0点到23:59:59）
                if (request.LssueDate != DateTime.MinValue)
                {
                    DateTime startDate = request.LssueDate.Date;
                    DateTime endDate = startDate.AddDays(1).AddSeconds(-1);
                    
                    query = query.Where(x => x.LssueDate >= startDate && x.LssueDate <= endDate);
                    
                    logger.LogInformation($"按发放时间筛选：{startDate} 至 {endDate}");
                }
                
                // 如果提供了发放状态，则按状态筛选
                if (request.LssueState != 0)
                {
                    query = query.Where(x => x.LssueState == request.LssueState);
                }
                
                // 查询发放表记录 - 直接使用ToListAsync而不是通过原生SQL查询，避免字段名不匹配问题
                var lssueList = await query.ToListAsync(cancellationToken);
                
                // 构建返回结果
                var result = new List<SignDto>();
                
                foreach (var lssue in lssueList)
                {
                    // 转换为DTO
                    var signDto = new SignDto
                    {
                        Id = lssue.Id,
                        LssueCode = lssue.LssueCode,
                        LssueName = lssue.LssueName,
                        LssueDate = lssue.LssueDate,
                        AcceptName = lssue.AcceptName,
                        LssueState = lssue.LssueState,
                        LssueStateName = GetEnumDescription(lssue.LssueState)
                    };
                    
                    // 获取对应的发放明细表数据
                    var details = await lssueDetailRep.GetAll()
                        .Where(d => d.LssueId == lssue.Id && !d.IsDeleted)
                        .ToListAsync(cancellationToken);
                    
                    // 转换明细数据
                    foreach (var detail in details)
                    {
                        var detailDto = new SignDetailDto
                        {
                            Id = detail.Id,
                            LssueId = detail.LssueId,
                            MaterialType = detail.MaterialType,
                            MaterialTypeName = GetEnumDescription(detail.MaterialType),
                            MaterialId = detail.MaterialId,
                            MaterialCode = detail.MaterialCode,
                            MaterialName = detail.MaterialName,
                            LssueNum = detail.LssueNum
                        };
                        
                        // 添加到签收DTO的明细列表
                        signDto.Details.Add(detailDto);
                    }
                    
                    result.Add(signDto);
                    
                    logger.LogInformation($"发放单 {lssue.LssueCode} 包含 {details.Count} 条明细记录");
                }
                
                logger.LogInformation($"签收表列表查询成功，返回 {result.Count} 条记录");

                return new ApiResult<List<SignDto>>
                {
                    Code = ApiEnums.Success,
                    Data = result,
                    Msg = "签收表列表显示成功!"
                };
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"查询签收表列表时发生异常：{ex.Message}");
                
                return new ApiResult<List<SignDto>>
                {
                    Code = ApiEnums.Error,
                    Data = new List<SignDto>(),
                    Msg = $"查询签收表列表失败：{ex.Message}"
                };
            }
        }
        
        /// <summary>
        /// 获取枚举的描述信息
        /// </summary>
        /// <param name="value">枚举值</param>
        /// <returns>枚举的描述信息</returns>
        private string GetEnumDescription(Enum value)
        {
            FieldInfo field = value.GetType().GetField(value.ToString());
            DescriptionAttribute attribute = field.GetCustomAttribute<DescriptionAttribute>();
            return attribute?.Description ?? value.ToString();
        }
    }
}
